package cn.nexd.collector;

import android.content.Context;
import android.util.Log;

import java.util.ArrayList;
import java.util.List;

import cn.nexd.collector.beacon.BeaconCollectorTask;
import cn.nexd.collector.bean.BeaconScannerResult;
import cn.nexd.collector.bean.MixCollectorResult;
import cn.nexd.collector.bean.WifiCollectorResult;
import cn.nexd.collector.core.CollectorWrap;
import cn.nexd.collector.listener.BeaconCollectorListener;
import cn.nexd.collector.listener.MixCollectorListener;
import cn.nexd.collector.listener.WifiCollectorListener;
import cn.nexd.collector.thread.ThreadPoolManager;
import cn.nexd.collector.wifi.WifiCollectorTask;

/**
 * Created by codngfish on 16/5/5.
 */
public class NexdCollectorAgent {


    private static Context context;
    private NexdCollectorConfiguration collectorConfig;
    private WifiCollectorListener wifiCollectorListener;
    private BeaconCollectorListener beaconCollectorListener;
    private CollectorWrap wifiCollectorWrap;
    private CollectorWrap beaconCollectorWrap;
    private MixCollectorListener mixCollectorListener;
    private boolean collectorRunning = false;

    private NexdCollectorAgent() {
    }

    public static NexdCollectorAgent getCollectorAgent(Context context) {
        NexdCollectorAgent.context = context;
        return NexdCollectorAgentClassHolder.NEXD_COLLECTOR_AGENT;
    }

    private static class NexdCollectorAgentClassHolder {
        public static final NexdCollectorAgent NEXD_COLLECTOR_AGENT = new NexdCollectorAgent();
    }

    /**
     * 设置 Collector 的配置对象。
     *
     * @param collectorConfig
     * @see NexdCollectorConfiguration
     */
    public void setCollectorConfiguration(NexdCollectorConfiguration collectorConfig) {
        this.collectorConfig = collectorConfig;
    }


    /**
     * 设置 Wifi 采集器监听。
     *
     * @param wifiCollectorListener
     */
    public void setWifiCollectorListener(WifiCollectorListener wifiCollectorListener) {
        this.wifiCollectorListener = wifiCollectorListener;
    }

    /**
     * 设置Beacon采集器监听.
     *
     * @param beaconCollectorListener
     */
    public void setBeaconCollectorListener(BeaconCollectorListener beaconCollectorListener) {
        this.beaconCollectorListener = beaconCollectorListener;
    }

    public void setMixCollectorListener(MixCollectorListener mixCollectorListener) {
        this.mixCollectorListener = mixCollectorListener;
    }

    /**
     * 开启采集器。
     */
    public void startCollector() {
        if (mixCollectorListener != null) {
            if (!(collectorConfig.bluetoothCollectorEnable && collectorConfig.wifiCollectorEnable)) {
                Log.e("collector_error", "错误,使用混合采集前请确保setBluetoothCollectorEnable/setWifiCollectorEnable 为 true");
                return;
            }
        }

        initCollector();
        Log.d("startCollector", "Ready to start Collector");
        start();
    }

    private final void start() {
        Log.d("start", "start: ");
        ThreadPoolManager.getThreadPoolManagerInstance().start();

        if (wifiCollectorWrap != null && ((mixCollectorListener != null ? wifiCollectorListener = null : wifiCollectorListener) != null || mixCollectorListener != null)) {
            wifiCollectorWrap.startCollector();
        }

        if (beaconCollectorWrap != null && ((mixCollectorListener != null ? beaconCollectorListener = null : beaconCollectorListener) != null || mixCollectorListener != null)) {
            Log.d("start", "beacon start: ");
            beaconCollectorWrap.startCollector();
        }

        collectorRunning = true;
    }


    /**
     * 停止采集器。
     */
    public void stopCollector() {

        collectorRunning = false;
        if (wifiCollectorWrap != null) {
            wifiCollectorWrap.stopCollector();
        }

        if (beaconCollectorWrap != null) {
            beaconCollectorWrap.stopCollector();
        }
    }

    public void destroyCollector() {
        collectorRunning = false;
        if (wifiCollectorWrap != null) {
            wifiCollectorWrap.destroyCollector();
            wifiCollectorWrap = null;
            wifiCollectorListener = null;
        }

        if (beaconCollectorWrap != null) {
            beaconCollectorWrap.destroyCollector();
            beaconCollectorWrap = null;
            beaconCollectorListener = null;
        }

        ThreadPoolManager.getThreadPoolManagerInstance().shutdownThreadPool();
    }

    public boolean getIsCollectorRunning() {
        return collectorRunning;
    }

    private final void initCollector() {
        if (context == null) {
            throw new RuntimeException("Context must not be null");
        }

        if (collectorConfig == null) {
            collectorConfig = new NexdCollectorConfiguration.Buidler().build();
        }


        if (collectorConfig.wifiCollectorEnable) {
            wifiCollectorWrap = new CollectorWrap(new WifiCollectorTask(context, collectorConfig, new DefaultWifiCollectorListener()));
        }

        if (collectorConfig.bluetoothCollectorEnable) {
            Log.d("initCollector", "beaconCollectorWrap");
            beaconCollectorWrap = new CollectorWrap(new BeaconCollectorTask(context, collectorConfig, new DefaultBeaconCollectorListener()));
        }
    }

    private List<MixCollectorResult> mixCollectorResults = new ArrayList<>();

    private class DefaultWifiCollectorListener implements WifiCollectorListener {
        @Override
        public void onCollectionStart() {
            mixCollectorWifiOK = true;
            if (wifiCollectorListener != null) {
                wifiCollectorListener.onCollectionStart();
            }

            if (mixCollectorListener != null) {
                mixCollectorListener.onCollectionStart();
            }
        }

        @Override
        public void onCollectionSuccess(List<WifiCollectorResult> collectorResults) {
            mixCollectorWifiOK = true;
            if (wifiCollectorListener != null) {
                wifiCollectorListener.onCollectionSuccess(collectorResults);
            }

            if (mixCollectorListener != null) {
                ThreadPoolManager.getThreadPoolManagerInstance().addTask(new HandlerMixCollectorThread(collectorResults, beaconCollectorResults));
            }
        }

        @Override
        public void onCollectorFailed(NexdCollector.CollectorState collectorState) {
            mixCollectorWifiOK = false;
            if (wifiCollectorListener != null) {
                wifiCollectorListener.onCollectorFailed(collectorState);
            }
            if (mixCollectorListener != null) {
                ThreadPoolManager.getThreadPoolManagerInstance().addTask(new HandlerMixCollectorThread(null, beaconCollectorResults));
            }
        }

        @Override
        public void onCollectorInterrupt(NexdCollector.CollectorState collectorState) {
            mixCollectorWifiOK = false;
            if (wifiCollectorListener != null) {
                wifiCollectorListener.onCollectorInterrupt(collectorState);
            }
            if (mixCollectorListener != null) {
                ThreadPoolManager.getThreadPoolManagerInstance().addTask(new HandlerMixCollectorThread(null, beaconCollectorResults));
            }
        }
    }

    private boolean mixCollectorBeaconOK = false;
    private boolean mixCollectorWifiOK = false;
    private List<BeaconScannerResult> beaconCollectorResults = new ArrayList<>();

    private class DefaultBeaconCollectorListener implements BeaconCollectorListener {

        @Override
        public void onCollectionStart() {
            mixCollectorBeaconOK = true;
            if (beaconCollectorListener != null) {
                beaconCollectorListener.onCollectionStart();
            }
        }

        @Override
        public void onCollectionSuccess(List<BeaconScannerResult> collectorResults) {
            beaconCollectorResults.addAll(collectorResults);
            mixCollectorBeaconOK = true;
            if (beaconCollectorListener != null) {
                beaconCollectorListener.onCollectionSuccess(collectorResults);
            }
        }

        @Override
        public void onCollectorFailed(NexdCollector.CollectorState collectorState) {
            mixCollectorBeaconOK = false;
            if (beaconCollectorListener != null) {
                beaconCollectorListener.onCollectorFailed(collectorState);
            }
        }

        @Override
        public void onCollectorInterrupt(NexdCollector.CollectorState collectorState) {
            mixCollectorBeaconOK = false;
            if (beaconCollectorListener != null) {
                beaconCollectorListener.onCollectorInterrupt(collectorState);
            }
        }
    }

    private class HandlerMixCollectorThread implements Runnable {


        private List<WifiCollectorResult> wifiCollectorResults;
        private List<BeaconScannerResult> beaconScannerResults;

        public HandlerMixCollectorThread(List<WifiCollectorResult> wifiCollectorResults, List<BeaconScannerResult> beaconScannerResults) {
            this.wifiCollectorResults = wifiCollectorResults;
            this.beaconScannerResults = beaconScannerResults;
        }

        @Override
        public void run() {
            if (mixCollectorBeaconOK && mixCollectorWifiOK && wifiCollectorResults != null) {
                //ok
                // 处理 Beacon 数据
                for (BeaconScannerResult beaconScannerResult : this.beaconScannerResults) {
                    MixCollectorResult mixCollectorResult = new MixCollectorResult(beaconScannerResult.getBeaconName(), beaconScannerResult.getBeaconAddress(), beaconScannerResult.getRssi(), 1, beaconScannerResult.getUUID(), beaconScannerResult.getMajor(), beaconScannerResult.getMajor(), beaconScannerResult.getTimestamp());
                    mixCollectorResults.add(mixCollectorResult);
                }

                for (WifiCollectorResult wifiCollectorResult : this.wifiCollectorResults) {
                    MixCollectorResult mixCollectorResult = new MixCollectorResult(wifiCollectorResult.getWifiName(), wifiCollectorResult.getWifiAddress(), wifiCollectorResult.getRssi(), 0, "", -1, -1, wifiCollectorResult.getTimestamp());
                    mixCollectorResults.add(mixCollectorResult);
                }

                beaconCollectorResults.clear();
                List<MixCollectorResult> mixCollectorResultList = new ArrayList<>();
                mixCollectorResultList.addAll(mixCollectorResults);
                if (mixCollectorListener != null) {
                    mixCollectorListener.onCollectionSuccess(mixCollectorResultList);
                }
                mixCollectorResults.clear();
            } else {
                // not ok
                if (mixCollectorListener != null) {
                    mixCollectorListener.onCollectorInterrupt(NexdCollector.CollectorState.COLLECTOR_INTERRUPT_TYPE_NO_WIFI_BEACON_FOUND);
                    stopCollector();
                }
            }
        }
    }
}


